#ifndef _INCLUDE_LIST_H_
#define _INCLUDE_LIST_H_

#include "global.h"
#include "stdint.h"

#define offsetof(struct_type, member) (int)(&((struct_type*)0)->member)

#define elem2entry(struct_type, struct_member_name, elem_ptr)                  \
  (struct_type*)((int)elem_ptr - offsetof(struct_type, struct_member_name))

struct list_elem
{
  struct list_elem* prev;
  struct list_elem* next;
};

struct list
{
  // introducing two sentinel nodes simplifies linked list operations, ensuring
  // consistency between the head and tail operations.

  struct list_elem head; // head.next points to the first element
  struct list_elem tail; // tail.prev points to the last element
};

typedef bool(operation_func)(struct list_elem*, int arg);

void list_init(struct list* list);
void list_insert_before(struct list_elem* before, struct list_elem* elem);
void list_push(struct list* plist, struct list_elem* elem);
void list_iterate(struct list* plist);
void list_append(struct list* plist, struct list_elem* elem);
void list_remove(struct list_elem* pelem);
struct list_elem* list_pop(struct list* plist);
bool              list_empty(struct list* plist);
uint32_t          list_len(struct list* plist);
struct list_elem* list_traversal(struct list* plist, operation_func func,
                                 int arg);
bool              elem_find(struct list* plist, struct list_elem* obj_elem);

#endif // !_INCLUDE_LIST_H_
